﻿﻿using RestSharp;
using System;
using System.Net;
using System.Runtime.InteropServices.JavaScript;
using System.Text.Json;
using System.IO;
using Microsoft.Extensions.Logging;
using System.Threading;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Jpeg;

namespace VideoClient
{
    public class XhVideoClient
    {
        private readonly ILogger<XhVideoClient> logger;

        private readonly string _host;
        private readonly RestClient _client;

        public string AccessToken { get; private set; } = "";
        public string RefreshToken { get; private set; } = "";
        public string PlayCode { get; private set; } = "";

        private Timer? _renewTimer;

        public XhVideoClient(ILogger<XhVideoClient> logger)
        {
            this.logger = logger;
            string preferredHost = "https://video.9hello3r.cn:444";
            string fallbackHost = "http://47.108.206.80:5000";
            if (IsHostAvailable(preferredHost))
            {
                _host = preferredHost;
            }
            else
            {
                _host = fallbackHost;
            }
            Console.WriteLine($"_host: {_host}");
            logger.LogInformation($"_host: {_host}");
            _client = new RestClient(_host);
        }


        private bool IsHostAvailable(string host)
        {
            try
            {
                var client = new RestClient(host);
                var request = new RestRequest("/vapi/py/hello", Method.Get);
                var response = client.Execute(request);
                if (response.IsSuccessful && !string.IsNullOrEmpty(response.Content))
                {
                    using var doc = JsonDocument.Parse(response.Content);
                    var root = doc.RootElement;
                    if (root.TryGetProperty("code", out var codeElem) && codeElem.GetInt32() == 0)
                    {
                        return true;
                    }
                }
            }
            catch
            {
                // ignore
            }
            return false;
        }
        /// <summary>
        /// Login and save access_token and refresh_token to member variables.
        /// </summary>
        public string Login(string username, string password, out bool success)
        {
            var request = new RestRequest("/vapi/py/auth/login", Method.Post);
            request.AddJsonBody(new { username, password });

            var response = _client.Execute(request);
            if (response.StatusCode != HttpStatusCode.OK)
            {
                //logger.LogWarning($"Login failed with status code: {response.StatusCode}");
                success = false;
                AccessToken = string.Empty;
                RefreshToken = string.Empty;
                return response.Content ?? string.Empty;
            }
            var content = response.Content ?? string.Empty;

            try
            {
                using var doc = JsonDocument.Parse(content);
                var root = doc.RootElement;

                if (!root.TryGetProperty("code", out var codeElem) || codeElem.GetInt32() != 0)
                {
                    //logger.LogWarning($"Login failed with code: {codeElem.GetInt32()}");
                    success = false;
                    AccessToken = string.Empty;
                    RefreshToken = string.Empty;
                    return content; // Return the error message
                }
                if (root.TryGetProperty("data", out var data))
                {
                    if (data.TryGetProperty("access_token", out var accessTokenElem))
                        AccessToken = accessTokenElem.GetString() ?? string.Empty;
                    if (data.TryGetProperty("refresh_token", out var refreshTokenElem))
                        RefreshToken = refreshTokenElem.GetString() ?? string.Empty;
                }
            }
            catch (Exception) // ex was unused
            {
                //logger.LogWarning(ex.Message);
                success = false;
                return "Error parsing login response."; // Return a generic error message
                // Ignore JSON parse errors, keep tokens as empty string
            }
            success = true;
            StartAutoRenewToken(); // 登录成功后启动自动刷新
            return content;
        }

        /// <summary>
        /// Get device channels, returns a strongly-typed DevChResponse.
        /// </summary>
        public DevChResponse? GetDeviceChannels(string token)
        {
            var request = new RestRequest("/vapi/py/device_channels", Method.Get);
            request.AddHeader("Authorization", $"Bearer {token}");

            DevChResponse? response = _client.Get<DevChResponse>(request); // response can be null
            return response;
        }

        public string GetCode(string token)
        {
            var request = new RestRequest("/vapi/py/get_code", Method.Get);
            request.AddHeader("Authorization", $"Bearer {token}");

            var response = _client.Execute(request);
            var content = response.Content ?? string.Empty;

            try
            {
                using var doc = System.Text.Json.JsonDocument.Parse(content);
                var root = doc.RootElement;
                var dataCode = root.GetProperty("data").GetProperty("code").GetString();
                return dataCode ?? string.Empty;
            }
            catch
            {
                return string.Empty;
            }
        }


        public string VerifyPlay(string code)
        {
            var request = new RestRequest("/vapi/py/on_play", Method.Get);
            request.AddParameter("code", code);
            request.AddJsonBody(new { }); // Empty JSON body

            var response = _client.Execute(request);
            return response.Content ?? string.Empty;
        }

        public string GetLocalSnapshotPath(DevCh devCh)
        {
            string deviceId = devCh.Device;
            string channel = devCh.Channel;
            string devch = $"{deviceId}_{channel}";
            string appDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "xhvideoplay");
            string localPath = Path.Combine(appDataDir, $"{devch}.jpg");
            if (File.Exists(localPath))
                return localPath;
            return "images/notfound.jpg"; // 默认图片路径
        }

        public async Task DownloadAndUpdateSnapshotAsync(DevCh devCh, Action? onSnapshotUpdated = null)
        {
            string deviceId = devCh.Device;
            string channel = devCh.Channel;
            string devch = $"{deviceId}_{channel}";
            string appDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "xhvideoplay");
            if (!Directory.Exists(appDataDir))
                Directory.CreateDirectory(appDataDir);

            string localPath = Path.Combine(appDataDir, $"{devch}.jpg");
            string url = $"{_host}/vapi/py/snap-image/{devch}";

            await Task.Delay(TimeSpan.FromSeconds(5));

            try
            {
                using var httpClient = new HttpClient();
                var response = await httpClient.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    var bytes = await response.Content.ReadAsByteArrayAsync();
                    // 只有图片内容大于一定字节数才处理
                    if (bytes.Length > 100)
                    {
                        // 用 ImageSharp 缩放图片
                        using var image = SixLabors.ImageSharp.Image.Load(bytes);
                        image.Mutate(x => x.Resize(400, 300));
                        // 保存为 JPEG
                        await image.SaveAsJpegAsync(localPath, new JpegEncoder { Quality = 85 });
                        onSnapshotUpdated?.Invoke(); // 只在成功时调用
                    }
                    // 失败不调用回调，也不覆盖原有图片
                }
            }
            catch
            {
                // ignore
            }
        }


        // 登录成功后调用此方法
        private void StartAutoRenewToken()
        {
            // var refreshInterval = TimeSpan.FromSeconds(10);
            var refreshInterval = TimeSpan.FromMinutes(50);
            _renewTimer = new Timer(async _ =>
            {
                try
                {
                    await RenewAccessTokenAsync();
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "定时刷新AccessToken时发生未捕获异常");
                }
            }, null, refreshInterval, refreshInterval);
        }

        public async Task<bool> RenewAccessTokenAsync()
        {
            if (string.IsNullOrEmpty(RefreshToken))
                return false;

            try
            {
                using var httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", RefreshToken);
                var url = $"{_host}/vapi/py/auth/renew";
                var response = await httpClient.PostAsync(url, null);
                if (response.IsSuccessStatusCode)
                {
                    var json = await response.Content.ReadAsStringAsync();
                    using var doc = JsonDocument.Parse(json);
                    var root = doc.RootElement;

                    if (!root.TryGetProperty("code", out var codeElem) || codeElem.GetInt32() != 0)
                    {
                        logger.LogWarning($"刷新AccessToken失败，code: {codeElem.GetInt32()}");
                        _renewTimer?.Dispose();
                        return false;
                    }

                    if (root.TryGetProperty("data", out var data))
                    {
                        if (data.TryGetProperty("access_token", out var accessTokenElem))
                            AccessToken = accessTokenElem.GetString() ?? string.Empty;
                        if (data.TryGetProperty("refresh_token", out var refreshTokenElem))
                            RefreshToken = refreshTokenElem.GetString() ?? string.Empty;

                        logger.LogInformation($"AccessToken 已自动刷新。");
                        await RefreshPlayCodeAsync();
                        return true;
                    }
                }
                else
                {
                    logger.LogWarning($"刷新AccessToken失败，状态码: {response.StatusCode}");
                }
            }
            catch (Exception ex)
            {
                logger.LogError($"刷新AccessToken异常, {ex.Message}");
            }
            return false;
        }


        public event Action? PlayCodeRefreshed;

        public async Task RefreshPlayCodeAsync()
        {
            try
            {
                using var httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", AccessToken);
                var url = $"{_host}/vapi/py/get_code";
                var response = await httpClient.GetAsync(url);
                logger.LogInformation("PlayCode 请求发送。");
                if (response.IsSuccessStatusCode)
                {
                    var json = await response.Content.ReadAsStringAsync();
                    using var doc = JsonDocument.Parse(json);
                    var root = doc.RootElement;
                    if (root.TryGetProperty("data", out var data) && data.TryGetProperty("code", out var playCodeElem))
                    {
                        PlayCode = playCodeElem.GetString() ?? "";
                        logger.LogInformation("PlayCode 已刷新。");
                        PlayCodeRefreshed?.Invoke(); // 通知订阅者
                    }
                }
                else
                {
                    logger.LogWarning($"刷新PlayCode失败，状态码: {response.StatusCode}");
                }
            }
            catch (Exception ex)
            {
                string msg = $"刷新PlayCode异常, {ex.Message}";
                logger.LogError(msg);
            }
        }
    }
}
